package net.simflow.swf.analyzer.gui.ginfo.generator;

import java.util.ArrayList;
import java.util.LinkedHashMap;

import net.simflow.swf.analyzer.data.TupleStrInt;
import net.simflow.swf.analyzer.exec.data.ExecResult;
import net.simflow.swf.analyzer.exec.stats.data.ExecStats;
import net.simflow.swf.analyzer.graph.stats.data.GraphStats;
import net.simflow.swf.analyzer.network.data.Flow;
import net.simflow.swf.analyzer.stringtrans.ExecResultStringGenerator;
import net.simflow.swf.analyzer.stringtrans.ExecStatsStringGenerator;
import net.simflow.swf.analyzer.stringtrans.GraphStatsStringGenerator;

public class ExecGenerator extends AbstractGenerator {
	protected static final LinkedHashMap<String, Boolean> DEFAULT_CONFIG_GRAPH = new LinkedHashMap<String, Boolean>();
	protected static final LinkedHashMap<String, Boolean> DEFAULT_CONFIG_STATS = new LinkedHashMap<String, Boolean>();
	protected static final LinkedHashMap<String, Boolean> DEFAULT_CONFIG_RESULT = new LinkedHashMap<String, Boolean>();
	static {
		DEFAULT_CONFIG_GRAPH.put(GraphStats.GRAPH_NAME, true);
		DEFAULT_CONFIG_STATS.put(ExecStats.EXECUTION_TIME_DISTRIBUTION, true);
		DEFAULT_CONFIG_STATS.put(ExecStats.FLOW_EXEC_TIME, true);
		DEFAULT_CONFIG_STATS.put(ExecStats.FLOW_AVG_EXEC_TIME_DISTRIBUTION,
				true);
		DEFAULT_CONFIG_STATS.put(ExecStats.FLOW_MAX_EXEC_TIME_DISTRIBUTION,
				true);
		DEFAULT_CONFIG_STATS.put(ExecStats.FLOW_MIN_EXEC_TIME_DISTRIBUTION,
				true);
		DEFAULT_CONFIG_STATS.put(ExecStats.FLOW_TOTAL_COUNT_DISTRIBUTION, true);
		DEFAULT_CONFIG_STATS.put(ExecStats.FLOW_EXECUTED_COUNT_DISTRIBUTION,
				true);
		DEFAULT_CONFIG_STATS.put(ExecStats.FLOW_UNFINISHED_COUNT_DISTRIBUTION,
				true);
		DEFAULT_CONFIG_STATS.put(ExecStats.FLOW_OVER_ABILITY_TIME_DISTRIBUTION,
				true);
		DEFAULT_CONFIG_STATS.put(ExecStats.FLOW_TOTAL_COUNT, true);
		DEFAULT_CONFIG_STATS.put(ExecStats.FLOW_EXECUTED_COUNT, true);
		DEFAULT_CONFIG_STATS.put(ExecStats.FLOW_UNFINISHED_COUNT, true);
		DEFAULT_CONFIG_STATS.put(ExecStats.FLOW_OVER_ABILITY_TIME, true);
		DEFAULT_CONFIG_STATS.put(ExecStats.SERVICE_TOTAL_COUNT_DISTRIBUTION,
				true);
		DEFAULT_CONFIG_STATS.put(ExecStats.SERVICE_EXECUTED_COUNT_DISTRIBUTION,
				true);
		DEFAULT_CONFIG_STATS.put(
				ExecStats.SERVICE_UNFINISHED_COUNT_DISTRIBUTION, true);
		DEFAULT_CONFIG_STATS.put(ExecStats.SERVICE_TOTAL_COUNT, true);
		DEFAULT_CONFIG_STATS.put(ExecStats.SERVICE_EXECUTED_COUNT, true);
		DEFAULT_CONFIG_STATS.put(ExecStats.SERVICE_UNFINISHED_COUNT, true);
		DEFAULT_CONFIG_STATS.put(ExecStats.SERVICE_OVER_ABILITY_TIME, true);
		DEFAULT_CONFIG_STATS.put(ExecStats.SERVICE_AVG_WAIT_TIME_DISTRIBUTION,
				true);
		DEFAULT_CONFIG_STATS.put(ExecStats.SERVICE_MAX_WAIT_TIME_DISTRIBUTION,
				true);
		DEFAULT_CONFIG_STATS.put(ExecStats.SERVICE_MIN_WAIT_TIME_DISTRIBUTION,
				true);
		DEFAULT_CONFIG_STATS.put(ExecStats.SERVICE_WAIT_TIME, true);
		DEFAULT_CONFIG_STATS.put(
				ExecStats.SERVICE_OVER_ABILITY_TIME_DISTRIBUTION, true);

		DEFAULT_CONFIG_RESULT.put(ExecResult.ORIGINAL_EXECUTION_RESULT, false);
		DEFAULT_CONFIG_RESULT.put(ExecResult.TOTAL_STEP, false);
		DEFAULT_CONFIG_RESULT.put(ExecResult.SERVICE_SCHEDULE, false);
		DEFAULT_CONFIG_RESULT.put(ExecResult.SERVICE_ABILITY, false);
		DEFAULT_CONFIG_RESULT.put(ExecResult.FLOW_RELDEADLINE, false);
		DEFAULT_CONFIG_RESULT.put(ExecResult.FLOW_WEIGHT, false);
		DEFAULT_CONFIG_RESULT.put(ExecResult.FLOW_CREATION_SPEED, false);
	}

	public LinkedHashMap<String, Boolean> getDefaultConfigGraph() {
		return new LinkedHashMap<String, Boolean>(DEFAULT_CONFIG_GRAPH);
	}

	public LinkedHashMap<String, Boolean> getDefaultConfigStats() {
		return new LinkedHashMap<String, Boolean>(DEFAULT_CONFIG_STATS);
	}

	public LinkedHashMap<String, Boolean> getDefaultConfigResult() {
		return new LinkedHashMap<String, Boolean>(DEFAULT_CONFIG_RESULT);
	}

	private Flow flow;

	private static ExecGenerator instance = new ExecGenerator();

	private ExecGenerator() {
	}

	public static ExecGenerator getInstance() {
		return instance;
	}

	public ArrayList<TupleStrInt> generate(GraphStats gstats,
			ExecResult eresult, ExecStats estats,
			LinkedHashMap<String, Boolean> cgstats,
			LinkedHashMap<String, Boolean> cresult,
			LinkedHashMap<String, Boolean> cstats) {
		return this
				.gen(gstats, eresult, estats, cgstats, cresult, cstats, null);
	}

	public ArrayList<TupleStrInt> generate(GraphStats gstats,
			ExecResult eresult, ExecStats estats,
			LinkedHashMap<String, Boolean> cgstats,
			LinkedHashMap<String, Boolean> cresult,
			LinkedHashMap<String, Boolean> cstats, Flow flow) {
		return this
				.gen(gstats, eresult, estats, cgstats, cresult, cstats, flow);
	}

	private ArrayList<TupleStrInt> gen(GraphStats gstats, ExecResult eresult,
			ExecStats estats, LinkedHashMap<String, Boolean> cgstats,
			LinkedHashMap<String, Boolean> cresult,
			LinkedHashMap<String, Boolean> cstats, Flow flow) {
		if (eresult == null || cresult == null || estats == null
				|| cstats == null) {
			return null;
		}

		this.flow = flow;

		ArrayList<TupleStrInt> info = new ArrayList<TupleStrInt>();

		info.addAll(super.generate(gstats, cgstats));
		info.addAll(super.generate(estats, cstats));
		info.addAll(super.generate(eresult, cresult));

		return info;
	}

	@Override
	public LinkedHashMap<String, Boolean> getDefaultConfig() {
		LinkedHashMap<String, Boolean> map = new LinkedHashMap<String, Boolean>();
		map.putAll(DEFAULT_CONFIG_GRAPH);
		map.putAll(DEFAULT_CONFIG_STATS);
		map.putAll(DEFAULT_CONFIG_RESULT);

		return map;
	}

	@Override
	protected String getTitle(Object stats) {
		if (stats.getClass() == GraphStats.class) {
			return "Graph";
		} else if (stats.getClass() == ExecResult.class) {
			return "Execution Result";
		} else if (stats.getClass() == ExecStats.class) {
			return "Execution Stats";
		}
		return null;
	}

	@Override
	protected ArrayList<TupleStrInt> getInfo(String style, Object stats) {
		if (this.flow == null) {
			if (stats.getClass() == GraphStats.class) {
				return GraphStatsStringGenerator.getInstance().generate(style,
						(GraphStats) stats);
			} else if (stats.getClass() == ExecResult.class) {
				return ExecResultStringGenerator.getInstance().generate(style,
						(ExecResult) stats);
			} else if (stats.getClass() == ExecStats.class) {
				return ExecStatsStringGenerator.getInstance().generate(style,
						(ExecStats) stats);
			}
		} else {
			if (stats.getClass() == GraphStats.class) {
				return GraphStatsStringGenerator.getInstance().generate(style,
						(GraphStats) stats);
			} else if (stats.getClass() == ExecResult.class) {
				return ExecResultStringGenerator.getInstance().generate(style,
						(ExecResult) stats, flow);
			} else if (stats.getClass() == ExecStats.class) {
				return ExecStatsStringGenerator.getInstance().generate(style,
						(ExecStats) stats, flow);
			}
		}
		return null;
	}
}
